import {computed, createStore, delay, designPage, reactive, toArray, useRefs} from "@peryl/react-compose";
import {$dialog, Button, ButtonGroup, eTreeDropType, Input, iTreeDragChangeData, iTreeNode, iTreeNodeWithMenuOption, Layout, LayoutSection, PageCard, PageCardContent, PageCardTitle, Space, Tooltip, Tree, TreeNodeWithMenu} from "plain-design";
import {env} from "../../env";
import {EntityListUtils, iEntity, iEntityFieldItem, iEntityGeneralityItem, iParseEntity, NodeIconMap} from "./entity-list.utils";
import {insertSort} from "@peryl/utils/insertSort";
import {deepcopy} from "@peryl/utils/deepcopy";

const layoutSize = createStore({
  initialState: 325,
  getCacheConfig: () => ({
    cacheName: 'entity-list-page-tree-size',
    envName: env.envName,
  })
});

export default designPage(() => {

  const { refs, onRef } = useRefs({ tree: Tree });

  const state = reactive({
    /*实体类型数据信息*/
    entityData: [] as iEntity[],
    /*当前是否处于加载状态*/
    loading: false,
    /*搜索实体关键词*/
    searchText: '',
  });

  /*已经解析的实体类型数据*/
  const parseEntities = computed(() => state.entityData.map(i => EntityListUtils.parseEntity(i)));

  const utils = {
    /*在新建实体类型、字段、泛型之后，检查是否需要自动滚动到底部*/
    autoCheckScroll: async () => {
      const refsScroll = refs.tree?.refs.list?.refs.scroll;
      if (!refsScroll) {return;}
      await delay(78);
      const { contentHeight, hostHeight } = refsScroll.state;
      const maxScrollTop = contentHeight - hostHeight;
      if (maxScrollTop - refsScroll.freezeState.wrapperScrollTop < 100) {
        refsScroll.methods.autoScrollBottom();
      }
    },
    /*重新加载数据*/
    reloadData: async () => {
      state.loading = true;
      const data = await EntityListUtils.getAllEntities();
      state.entityData = data;
      state.loading = false;
    },
    /*创建一个实体类型*/
    createEntity: async () => {
      const newEntity = await EntityListUtils.createEntity({ parseEntities: parseEntities.value });
      const maxSeq = state.entityData.filter(i => !i.isInternal).reduce((prev, item) => Math.max(item.seq, prev), 0);
      newEntity.seq = maxSeq + 1;
      const insertEntity = await EntityListUtils.requestInsert(newEntity);
      state.entityData.push(insertEntity);
      await utils.autoCheckScroll();
    },
    /*发送请求更新实体类型*/
    requestUpdateEntity: async (newEntity: iEntity | iEntity[]) => {
      const updateEntities = await EntityListUtils.requestUpdate(toArray(newEntity));
      updateEntities.forEach(updateEntity => {
        const index = state.entityData.findIndex(i => i.id === updateEntity.id);
        if (index > -1) {
          state.entityData[index] = updateEntity;
        }
      });
    },
    /*编辑实体类型*/
    editEntity: async (parseEntity: iParseEntity) => {
      const newEntity = await EntityListUtils.editEntity({ entity: EntityListUtils.reverseParseEntity(parseEntity), parseEntities: parseEntities.value });
      await utils.requestUpdateEntity(newEntity);
    },
    /*删除一个实体类型*/
    removeEntity: async (parseEntity: iParseEntity) => {
      await $dialog.confirm(`删除实体：${parseEntity.title}`, { title: '确认提示' });
      await EntityListUtils.requestDelete(parseEntity.id);
      const index = state.entityData.findIndex(i => i.id === parseEntity.id);
      if (index > -1) {state.entityData.splice(index, 1);}
    },
    /*创建一个泛型类型*/
    createGeneralityItem: async (parseEntity: iParseEntity) => {
      const newGeneralityItem = await EntityListUtils.createGeneralityItem({ parseEntity });
      const newParseEntity = deepcopy(parseEntity);
      newParseEntity.generalityConfig.push(newGeneralityItem);
      await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(newParseEntity));
      await utils.autoCheckScroll();
    },
    /*编辑一个泛型类型*/
    editGeneralityItem: async (parseEntity: iParseEntity, generalityItem: iEntityGeneralityItem) => {
      const newGeneralityItem = await EntityListUtils.editGeneralityItem({ generalityItem, parseEntity });
      const newParseEntity = deepcopy(parseEntity);
      const index = newParseEntity.generalityConfig.findIndex(i => i.code === newGeneralityItem.code);
      newParseEntity.generalityConfig[index] = newGeneralityItem;
      await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(newParseEntity));
    },
    /*删除一个泛型*/
    removeGeneralityItem: async (parseEntity: iParseEntity, generalityItem: iEntityGeneralityItem) => {
      await $dialog.confirm(`删除泛型：${generalityItem.title}`);
      const newParseEntity = deepcopy(parseEntity);
      const index = newParseEntity.generalityConfig.findIndex(i => i.code === generalityItem.code);
      newParseEntity.generalityConfig.splice(index, 1);
      await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(newParseEntity));
    },
    /*创建一个字段*/
    createFieldItem: async (parseEntity: iParseEntity) => {
      const newFieldItem = await EntityListUtils.createFieldItem({ parseEntities: parseEntities.value, parseEntity });
      const newParseEntity = deepcopy(parseEntity);
      newParseEntity.fieldConfig.push(newFieldItem);
      await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(newParseEntity));
      delay().then(() => {refs.tree?.methods.expand(newParseEntity.id);});
      await utils.autoCheckScroll();
    },
    /*编辑一个字段*/
    editFieldItem: async (parseEntity: iParseEntity, fieldItem: iEntityFieldItem) => {
      const newFieldItem = await EntityListUtils.editFieldItem({ fieldItem, parseEntities: parseEntities.value, parseEntity });
      const newParseEntity = deepcopy(parseEntity);
      const index = newParseEntity.fieldConfig.findIndex(i => i.code === newFieldItem.code);
      newParseEntity.fieldConfig[index] = newFieldItem;
      await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(newParseEntity));
    },
    /*删除一个字段*/
    removeFieldItem: async (parseEntity: iParseEntity, fieldItem: iEntityFieldItem) => {
      await $dialog.confirm(`删除字段：${fieldItem.title}`);
      const newParseEntity = deepcopy(parseEntity);
      const index = newParseEntity.fieldConfig.findIndex(i => i.code === fieldItem.code);
      newParseEntity.fieldConfig.splice(index, 1);
      await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(newParseEntity));
    },
  };

  utils.reloadData().then(() => {console.log(parseEntities.value);});

  const handler = {
    /*处理字段筛选，支持搜索标题以及编码*/
    filterMethod: (nodeData: any, filterText: string): boolean => {
      const cascadeNodeData = nodeData as iCascadeNodeData;
      return [cascadeNodeData.data.title, cascadeNodeData.data.code].some(i => i.toLowerCase().indexOf(filterText.toLowerCase()) > -1);
    },
    /*当搜索关键词变化时，自动收起或者展开所有节点*/
    onSearchChange: (searchText?: string) => {
      !searchText?.trim().length ?
        refs.tree?.methods.collapseAll() :
        refs.tree?.methods.expandAll();
    },
    /*拖拽发生变化时，持久化更新实体类型数据*/
    onDragChange: async ({ newParentNode, oldParentNode, newSiblings, data, node }: iTreeDragChangeData) => {
      if (newParentNode?.id === oldParentNode?.id) {
        /*仅调整兄弟节点顺序*/
        const cascadeNodeData = data as iCascadeNodeData;
        switch (cascadeNodeData.type) {
          case "entity":
            const siblingsParseEntities = (newSiblings as iCascadeNodeData[]).map(i => i.data as iParseEntity);
            const changeParseEntities = siblingsParseEntities
              .filter((i) => !i.isInternal)
              .filter((item, index) => {
                const targetSeq = index + 1;
                const isChange = targetSeq != item.seq;
                if (isChange) {
                  item.seq = targetSeq;
                  return true;
                }
                return false;
              });
            await utils.requestUpdateEntity(changeParseEntities.map(i => EntityListUtils.reverseParseEntity(i)));
            return;
          case "generality":
            await (async () => {
              const parentParseEntity = deepcopy((node.parent!.data as iCascadeNodeData).data as iParseEntity);
              parentParseEntity.generalityConfig = (newSiblings as iCascadeNodeData[]).filter(i => i.type === 'generality').map(i => i.data) as any;
              await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(parentParseEntity));
            })();
            return;
          case "field":
            await (async () => {
              const parentParseEntity = deepcopy((node.parent!.data as iCascadeNodeData).data as iParseEntity);
              parentParseEntity.fieldConfig = (newSiblings as iCascadeNodeData[]).filter(i => i.type === 'field').map(i => i.data) as any;
              await utils.requestUpdateEntity(EntityListUtils.reverseParseEntity(parentParseEntity));
            })();
            return;
        }
      } else {
        const newParentParseEntity = (newParentNode!.data as iCascadeNodeData).data as iParseEntity;
        newParentParseEntity.generalityConfig = ((newParentNode!.childrenData() || []) as iCascadeNodeData[]).filter(i => i.type === 'generality').map(i => i.data) as any;
        newParentParseEntity.fieldConfig = ((newParentNode!.childrenData() || []) as iCascadeNodeData[]).filter(i => i.type === 'field').map(i => i.data) as any;

        const oldParentParseEntity = (oldParentNode!.data as iCascadeNodeData).data as iParseEntity;
        oldParentParseEntity.generalityConfig = ((oldParentNode!.childrenData() || []) as iCascadeNodeData[]).filter(i => i.type === 'generality').map(i => i.data) as any;
        oldParentParseEntity.fieldConfig = ((oldParentNode!.childrenData() || []) as iCascadeNodeData[]).filter(i => i.type === 'field').map(i => i.data) as any;

        await utils.requestUpdateEntity([
          EntityListUtils.reverseParseEntity(newParentParseEntity),
          EntityListUtils.reverseParseEntity(oldParentParseEntity)
        ]);
      }
    },
    /*节点的更多选项按钮，不同类型的节点的选项按钮不同*/
    getTreeNodeOptions: (treeNode: iTreeNode): iTreeNodeWithMenuOption[] => {
      const data = treeNode.data as iCascadeNodeData;
      switch (data.type) {
        case "entity":
          return [
            { label: '新建泛型', icon: 'ri-question-mark', onClick: () => {utils.createGeneralityItem(data.data);}, },
            { label: '新建字段', icon: 'ri-text', onClick: () => {utils.createFieldItem(data.data);}, },
            { label: '编辑实体', icon: 'ri-pencil-line', onClick: () => {utils.editEntity(data.data);}, },
            { label: '删除实体', icon: 'ri-close-line', onClick: () => {utils.removeEntity(data.data);}, },
          ];
        case "generality":
          return [
            { label: '编辑泛型', icon: 'ri-pencil-line', onClick: () => {utils.editGeneralityItem(treeNode.parent!.data.data, data.data);}, },
            { label: '删除泛型', icon: 'ri-close-line', onClick: () => {utils.removeGeneralityItem(treeNode.parent!.data.data, data.data);}, },
          ];
        case "field":
          return [
            { label: '编辑字段', icon: 'ri-pencil-line', onClick: () => {utils.editFieldItem(treeNode.parent!.data.data, data.data);}, },
            { label: '删除字段', icon: 'ri-close-line', onClick: () => {utils.removeFieldItem(treeNode.parent!.data.data, data.data);}, },
          ];
      }
    },
    /*节点的图标，不同类型的节点图标不同*/
    leafIcon: (treeNode: iTreeNode): string => {
      if (treeNode.empty) {
        return NodeIconMap.empty!;
      }
      const cascadeNodeData = treeNode.data as iCascadeNodeData;
      switch (cascadeNodeData.type) {
        case "entity":
          return NodeIconMap[cascadeNodeData.id] || NodeIconMap.unknown!;
        case "generality":
          return NodeIconMap.generality!;
        case "field":
          return (!cascadeNodeData.data.entityCode?.sec ? undefined : NodeIconMap[cascadeNodeData.data.entityCode.sec]) || NodeIconMap.entity!;
      }
    },
    /*动态判断节点是否允许拖拽，基础数据类型的节点以及内置的节点不允许拖拽移动，都放在最上边*/
    isAllowDraggable: (treeNode: iTreeNode) => {
      const cascadeNodeData = treeNode.data as iCascadeNodeData;
      return !(cascadeNodeData.type === 'entity' && cascadeNodeData.data.isInternal);
    },
    /*动态判断节点是否允许防止，不允许放置在内置节点的上面或者里边*/
    isAllowDroppable: (startNode: iTreeNode, moveNode: iTreeNode, dropType: typeof eTreeDropType.TYPE) => {
      const moveNodeData = moveNode.data as iCascadeNodeData;
      if (moveNodeData.type === 'entity' && moveNodeData.data.isInternal) {return false;}

      if (dropType === eTreeDropType.inner) {
        return (startNode.data as iCascadeNodeData).type !== 'entity' && (moveNode.data as iCascadeNodeData).type === 'entity';
      } else {
        /*只有同级之间的节点才可以移动到前/后位置*/
        return startNode.level === moveNode.level && (startNode.data as iCascadeNodeData).type === (moveNode.data as iCascadeNodeData).type;
      }
    },
    isCheckAble: () => false,
  };

  /*计算树形节点数据*/
  const cascadeData = computed((): iCascadeNodeData[] => {
    return insertSort(state.entityData, (a, b) => a.seq > b.seq).map((item): iCascadeNodeData => {
      const parseEntity = EntityListUtils.parseEntity(item);
      return {
        id: item.id,
        label: `${item.title} ( ${item.code} )`,
        data: parseEntity,
        type: 'entity',
        ...item.isBasic ? {} : {
          children: (() => {
            const ret: iCascadeNodeData[] = [];
            ret.push(...parseEntity.generalityConfig.map((genItem): iCascadeNodeData => ({
              id: genItem.code,
              label: `${genItem.title} ( ${genItem.code} )`,
              data: genItem,
              type: 'generality'
            })));
            ret.push(...parseEntity.fieldConfig.map((fieldItem): iCascadeNodeData => ({
              id: fieldItem.code,
              label: `${fieldItem.title} ( ${fieldItem.code} / ${EntityListUtils.getGeneralityEntityName(fieldItem.entityCode, parseEntities.value)})`,
              data: fieldItem,
              type: 'field'
            })));
            return ret;
          })()
        }
      };
    });
  });

  return () => (
    <PageCard full>
      <PageCardContent full noPadding>
        <Layout style={{ height: '100%' }}>
          <LayoutSection position="left" v-model={layoutSize.value}>
            <PageCard full>
              <PageCardTitle title="实体列表">
                <Space size="mini">
                  <ButtonGroup>
                    {/*<Tooltip message="全部选中"><Button icon="ri-list-check-3" onClick={() => refs.tree?.methods.checkAll()}/></Tooltip>*/}
                    {/*<Tooltip message="清空选中"><Button icon="ri-list-check-2" onClick={() => refs.tree?.methods.unCheckAll()}/></Tooltip>*/}
                    <Tooltip message="全部收起"><Button icon="ri-indent-decrease" onClick={() => refs.tree?.methods.collapseAll()}/></Tooltip>
                    <Tooltip message="全部展开"><Button icon="ri-indent-increase" onClick={() => refs.tree?.methods.expandAll()}/></Tooltip>
                  </ButtonGroup>
                  <Tooltip message="新建"><Button icon="ri-menu-add-line" onClick={utils.createEntity}/></Tooltip>
                </Space>
              </PageCardTitle>
              <PageCardContent>
                <Input suffixIcon="pi-search" placeholder="搜索实体/泛型/字段" v-model={state.searchText} onChange={handler.onSearchChange}/>
              </PageCardContent>
              <PageCardContent full>
                <Tree
                  ref={onRef.tree}
                  data={cascadeData.value}
                  filterText={state.searchText}
                  filterMethod={handler.filterMethod}
                  labelField="label"
                  keyField="id"
                  childrenField="children"
                  loading={state.loading}
                  leafIcon={handler.leafIcon}
                  disableCurrent
                  virtual
                  onDragChange={handler.onDragChange}
                  draggable
                  customDraggier
                  expandOnClickNode
                  isAllowDraggable={handler.isAllowDraggable}
                  isAllowDroppable={handler.isAllowDroppable}
                  isCheckAble={handler.isCheckAble}
                  v-slots={{
                    default: ({ treeNode }: { treeNode: iTreeNode }) => {
                      const cascadeNodeData = treeNode.data as iCascadeNodeData;
                      const hideButton = cascadeNodeData.type === 'entity' && cascadeNodeData.data.isInternal;
                      return (
                        <TreeNodeWithMenu
                          treeNode={treeNode}
                          dropdownOptions={handler.getTreeNodeOptions(treeNode)}
                          hideButton={hideButton}
                        />);
                    }
                  }}
                />
              </PageCardContent>
            </PageCard>
          </LayoutSection>
          <LayoutSection>
            <PageCard>
              <PageCardContent>
                this is section content
              </PageCardContent>
            </PageCard>
          </LayoutSection>
        </Layout>
      </PageCardContent>
    </PageCard>
  );
});

type iCascadeNodeData = {
  id: string,
  label: string,
  children?: iCascadeNodeData[]
} & ({
  data: iParseEntity,
  type: 'entity',
} | {
  data: iEntityGeneralityItem,
  type: 'generality',
} | {
  data: iEntityFieldItem,
  type: 'field',
})
